#ifndef __THREAD_H__
#define __THREAD_H__

#include <ucontext.h>

/* identifiant de thread
 * NB: pourra être un entier au lieu d'un pointeur si ca vous arrange,
 *     mais attention aux inconvénient des tableaux de threads
 *     (consommation mémoire, cout d'allocation, ...).
 */
typedef void * thread_t;

typedef struct {
  thread_t id_thread;
  int state;
  int is_joined;
  ucontext_t attr;
  void * arg;
  void * (*function)(void *);
  void * result;
  int valgrind_stackid;

}thread_info;

/* recuperer l'identifiant du thread courant.
 */
extern thread_t thread_self(void);

/* creer un nouveau thread qui va exécuter la fonction func avec l'argument funcarg.
 * renvoie 0 en cas de succès, -1 en cas d'erreur.
 */
extern int thread_create(thread_t * newthread, ucontext_t * attr, void * (*func)(void *), void * funcarg);

/* initialiser le thread main
 */
void main_init (void);

/* lancer la fonction associée au thread et sa valeur de retour.
 */
void thread_wraper(void);


/* passer la main à un autre thread.
 */
extern int thread_yield(void);

/* attendre la fin d'exécution d'un thread.
 * la valeur renvoyée par le thread est placée dans *retval.
 * si retval est NULL, la valeur de retour est ignorée.
 */
extern int thread_join(thread_t thread, void **retval);

/* terminer le thread courant en renvoyant la valeur de retour retval.
 * cette fonction ne retourne jamais.
 *
 * L'attribut noreturn aide le compilateur à optimiser le code de
 * l'application (élimination de code mort). Attention à ne pas mettre
 * cet attribut dans votre interface tant que votre thread_exit()
 * n'est pas correctement implémenté (il ne doit jamais retourner).
 */
extern void thread_exit(void *retval) __attribute__((noreturn));

/*libérer le main à la fin de l execution des autres threads
 */
void main_free(void);


#endif /* __THREAD_H__ */
